using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Net;
using Microsoft.Devices;
using System.Device.Location;

namespace Balloon
{
    public delegate void MapLoadedEventHandler(object sender, OpenReadCompletedEventArgs e);

    public class MapClient
    {
        public event MapLoadedEventHandler MapLoaded;

        int _scale;
        private const string _bingAppKey = "Ao32v14Pi4R4B0ICm6tLPrZdJ8Gyf8XHx5yZFzQYdUq2_sx_ViG4_5R0dRaMlxnF";

        GeoCoordinateWatcher _watcher;
        GeoCoordinate _co;

        public MapClient()
        {
            _scale = 19;
        }

        internal void Initialize()
        {
            if (Microsoft.Devices.Environment.DeviceType == DeviceType.Device)
            {
                _watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); // Use high accuracy.
                _watcher.MovementThreshold = 20; // Use MovementThreshold to ignore noise in the signal.
                _watcher.StatusChanged += (sender, e) =>
                {
                    if (e.Status == GeoPositionStatus.Ready)
                    {
                        _co = _watcher.Position.Location;
                        _watcher.Stop(); //Stop to conserve the battery - will disable the movement updates
                        update_map();
                    }
                };
                _watcher.Start();
            }
            else
            {
                // somewhere near vantajokki
                _co = new GeoCoordinate(60.23673511, 24.98710966);
                update_map();
            }
        }

        void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
            MapLoaded(sender, e);
        }

        // handles every accelerometer read event
        public void on_acl_read(object sender, AclReadEventArgs e)
        {
            Vector3 acceleration = e.AclReading.Acceleration;

            // X value affect current coordinate's latitude value
            // _scale value will effect the speed of change
            // So when balloon is low map does not change too rapidly
            // we have some coefficient value 200 to make the effect smaller
            _co.Latitude += acceleration.X / (_scale * 200);
            // If balloon goes beyond the polls correct the value
            if (_co.Latitude > 90)
            {
                _co.Latitude = 90 - (_co.Latitude - 90);
                _co.Longitude = -_co.Longitude;
            }
            else if (_co.Latitude < -90)
            {
                _co.Latitude = 180 + _co.Latitude;
                _co.Longitude = -_co.Longitude;
            }
            // Y value affect the longitude value
            _co.Longitude -= acceleration.Y/ (_scale*200);
            if (_co.Longitude > 180)
            {
                _co.Longitude = _co.Longitude - 360;
            }
            else if (_co.Longitude < -180)
            {
                _co.Longitude = _co.Longitude + 360;
            }

            update_map();
        }

        void update_map()
        {
            string _requestUri = "";
            WebClient _wc = new WebClient();
            _requestUri = string.Format("http://dev.virtualearth.net/REST/V1/Imagery/Map/Aerial/{0},{1}/{3}?mapSize=800,480&key={2}",
                            _co.Latitude, _co.Longitude,
                            _bingAppKey, _scale);
            _wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
            _wc.OpenReadAsync(new Uri(_requestUri, UriKind.Absolute));
        }

        internal void fire()
        {
            int temp = (_scale > 1) ? --_scale : 1;
            if (temp != _scale)
            {
                _scale = temp;
                update_map();
            }
        }

        internal void ice()
        {
            int temp = (_scale < 19) ? ++_scale : 19;
            if (temp != _scale)
            {
                _scale = temp;
                update_map();
            }
        }
    }
}
